# 12장 파드 스케줄링

Assembled by GimunLee


# 파드 스케줄링

  • 특정 파드들을 노드 하나에 모아두거나 특정 IP 대역의 노드들에서만 실행
  • 같은 기능이 있는 파드들이 노드 하나에 몰려있지 않도록 분산 실행
  • 관리가 필요한 노드가 있을때 해당 노드에 있는 파드들을 다른 노드로 이동

# 노드셀렉터

  • 가장 간단한 스케줄링 옵션을 .spec 필드에 설정 가능한 노드셀렉터가 있음
  • 파드가 클러스터 안 어떤 노드에서 실행될지를 키-값 쌍으로 설정
  • 노드셀렉터는 노드의 레이블에 설정된 값으로 노드를 선택
apiVersion: v1
kind: Pod
metadata:
  name: kubernetes-nodeselector-pod
spec:
  containers:
  - name: kubernetes-nodeselector-pod
    image: arisu1000/simple-container-app:latest
    ports:
    - containerPort: 8080
  nodeSelector: 
    disktype: ssd  # disktype이 ssd인 노드에 실행 가능

# 어피니티와 안티 어피니티

  • 파드들을 함께 묶어서 같은 노드에서 실행하도록 설정하는 어피니티와 파드들을 다른 노드에 나누어서 실행하도록 설정하는 안티 어피니티

# 노드 어피니티(Node affinity)

  • 노드 어피니티는 노드셀렉터와 비슷하게 노드의 레이블 기반으로 파드를 스케줄링
  • 노드 어피니티와 노드셀렉터를 함께 설정할 수 있으며 이때는 노드 어피니티와 노드셀렉터의 조건을 모두. 만족하는 노드에 파드를 스케줄링
  • requiredDuringSchedulingIgnoredDuringExecution,preferredDuringSchedulingIgnoredDuringExecution 두 필드는 실행 중에 조건이 바뀌어도 무시; 파드가 이미 스케줄링되어 특정 노드에서 실행 중이라면 중간에 해당 노드의 조건이 변경되더라도 이미 실행 중인 파드는 그대로 실행된다는 뜻
apiVersion: v1
kind: Pod
metadata:
  name: kubernetes-nodeaffinity-pod
spec:
  containers:
  - name: kubernetes-nodeaffinity-pod
    image: arisu1000/simple-container-app:latest
    ports:
    - containerPort: 8080
  affinity: # 어피니티 설정
    nodeAffinity: # 노드 어피니티
      requiredDuringSchedulingIgnoredDuringExecution: # 스케줄링하는 동안 꼭 필요한 조건
        nodeSelectorTerms: # 노드 어피니티 유형
        - matchExpressions: # 연관된 노드셀렉터 설정을 연결하는 필드
          - key: beta.kubernetes.io/os # 노드의 레이블 키 중 하나를 설정
            operator: In # 키가 만족할 조건 
	            # In: .values[] 필드에 설정한 값 중 레입ㄹ에 있는 값과 일치하는 것이 하나라도 있는지 확인
	            # NotIn: In과 반대로 .values[] 필드에 있는 값 모두와 맞지 않는지 확인
	            # Exists: .values[] 필드가 필요 없고 .key 필드에 설정한 값이 레이블에 있는지만 확인
	            # DoesNotExist: Exists와 반대
	            # Gt: Greater than으로 .values[] 필드에 설정된 값보다 큰 숫자형 데이터인지를 확인. values에 값이 하나만 있어야함
	            # Lt: Lower than으로 Gt와 반대
            values:
            - linux
            - window
          - key: disktype
            operator: Exists
          # - key: core
            # operator: Gt
            # values:
            # - "4"
      preferredDuringSchedulingIgnoredDuringExecution: # 필수는 아니지만 스케줄링하는 동안 만족하면 좋은 조건
      - weight: 10 # 1부터 100까지의 값 설정 가능; 노드의 설정이 맞을 때 마다 .weight 필드 값을 더하고, .weight 합산이 가장 큰 노드를 선택
        preference: # 해당 조건에 맞는 걸 선호
          matchExpressions:
          - key: kubernetes.io/hostname
            operator: In
            values:
            - worker-node01

# 파드의 어피니티와 안티 어피니티

  • 파드 사이의 어피니티와 안티 어피니티는 디플로이먼트나 스테이트풀세트로 파드를 배포했을 때 개별 파드 사이의 관계를 정의하는 용도로 사용

# 어피니티

  • 컨테이너로 서비스를 운영하다 보면 서비스 A의 파드와 서비스 B의 파드 사이에 자주 통신할 때가 있는데, 이때 이 두 파드를 같은 노드에 속하게 만들어 효율을 높임
  • 가장 흔한 예로 데이터베이스나 캐시 같은 서비스와 통신하는 앱 컨테이너를 같은 노드에 두어 네트워크 통신 비용을 줄이는 것

# 안티 어피니티

  • CPU나 네트워크 같은 하드웨어 자원을 많이 사용하는 앱 컨테이너가 있을 때 여러 노드로 파드를 분산하는 것
  • 안티 어피니티를 설정하지 않으면 디플로이먼트로 배포한 파드가 노드 하나에서만 실행되어 자원을 많이 소모할 수 있음
apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis-cache
spec:
  selector:
    matchLabels:
      app: store
  replicas: 2
  template:
    metadata:
      labels:
        app: store
    spec:
      affinity: 
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - store # app 필드 값이 store인 파드가 속한 노드를 피해서 파드를 추가한다는 설정 	
            topologyKey: "kubernetes.io/hostname"
      containers:
      - name: redis-server
        image: redis:3.2-alpine

# 테인트와 톨러레이션

  • 쿠버네티스 클러스터의 특정 노드에 테인트를 설정할 수 있는데, 테인트를 설정하면 설정한 노드에는 파드들을 스케줄링하지 않음
  • 테인트를 설정한 노드에 파드들을 스케줄링하기 위해서는 톨러레이션을 설정해야함
  • 테인트는 톨러레이션에서 설정한 특정 파드들만 실행하고 다른 파드는 실행하지 못하게 함
  • 테인트와 톨러레이션은 주로 노드를 특정 역할만 하도록 만들 때 사용
  • 예를 들어 데이터베이스용 파드를 실행한 후 노드 전체의 CPU나 RAM 자원을 독점해서 사용할 수 있도록 설정하는 것
  • 테인트는 키, 값, 효과의 세 가지로 구성됨. kubectl taint nodes {노드이름} {키=값:효과}
apiVersion: apps/v1
kind: Deployment
metadata:
  name: kubernetes-simple-app
  labels:
    app: kubernetes-simple-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: kubernetes-simple-app
  template:
    metadata:
      labels:
        app: kubernetes-simple-app
    spec:
      containers:
      - name: kubernetes-simple-app
        image: arisu1000/simple-container-app:latest
        ports:
        - containerPort: 8080
      tolerations: # 테인트가 설정된 노드에 실행시키기 위한 톨러레이션 설정
      - key: "key01"
        operator: "Equal"
        value: "value01"
        effect: "NoSchedule"
        	# NoSchedule: 톨러레이션 설정이 없으면 파드를 스케줄링하지 않음. 기존에 실행되던 파드에는 적용되지 않음
        	# PreferNoSchedule: 톨러레이션 설정이 없으면 파드를 스케줄링하지 않음. 하지만 자원이 부족하면 스케줄링 가능
        	# NoExecute: 톨러레이션 설정이 없으면 새로운 파드를 스케줄링하지 않음. 기존 파드도 테인트 설정을 무시할수 있는 톨러레이션 설정이 없으면 종료 

# 클러스터를 관리하는 커든과 드레인

  • 쿠버네티스를 사용하다 보면 특정 노드에 있는 파드들을 모두 다른 노드로 옮기거나 특정 노드에 파드들을 스케줄링하지 않도록 제한할 필요 존재

  • 커든(cordon): 지정된 노드에 추가로 파드를 스케줄링해서 실행하지 않도록 함

  • 드레인(drain)

    • 노드 관리 등의 이유로 지정된 노드에 있는 파드들을 다른 노드로 이동시키는 명령
    • 노드에 데몬세트로 실행한 파드들이 있으면 데몬세트로 실행한 파드들은 삭제해도 데몬세트가 즉시 재실행시키기 때문에 드레인 설정을 적용할 수 없음

# Referenses

  • 쿠버네티스 입문 - 90가지 예제로 배우는 컨테이너 관리 자동화 표준 / 동양북스
Last Updated: 8/12/2020, 1:33:42 PM